﻿using BaseFramework;
using BaseFramework.Core;
using BaseFramework.DbConnectionProvider;
using BaseFramework.Dialect;
using LiteFramework.Contract;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;

namespace LiteFramework.Server.Component
{
    public class CancelEventExArgs : CancelEventArgs
    {
        public CancelEventExArgs()
            : base()
        { }
        public CancelEventExArgs(bool cancel, string error = null)
            : base(cancel)
        {
            this.Error = error;
        }

        /// <summary>
        /// Cancel=true时的提示信息
        /// </summary>
        public string Error { get; set; }
    }

    public abstract class AbsComponent<T> : IAbsContract<T>
        where T : PersistentEntity<T>
    {
        protected readonly IDbConnectionProvider _connectionProvider = null;
        protected readonly IDictionary<string, IDbConnectionProvider> _compArgs = null;
        public AbsComponent(IDbConnectionProvider connectionProvider = null)
        {
            _connectionProvider = connectionProvider;
            if (_connectionProvider == null) _connectionProvider = ServerApplication.DefaultConnectionProvider();

            _compArgs = new Dictionary<string, IDbConnectionProvider>();
            _compArgs.Add("connectionProvider", _connectionProvider);
        }
        protected virtual IDbConnectionProvider connectionProvider { get { return _connectionProvider; } }


        #region abstract mark_TaskCode_***
        /// <summary>
        /// 通过重写此方法，并标以AccessSecurity属性标签，指定其TaskCodes，实现过滤权限：查阅
        /// </summary>
        //[AccessSecurity(SecurityAction.Demand)]
        protected virtual void check_TaskRight_Get() { }
        /// <summary>
        /// 通过重写此方法，并标以AccessSecurity属性标签，指定其TaskCodes，实现过滤权限：保存
        /// </summary>
        //[AccessSecurity(SecurityAction.Demand)]
        protected virtual void check_TaskRight_Create() { }
        /// <summary>
        /// 通过重写此方法，并标以AccessSecurity属性标签，指定其TaskCodes，实现过滤权限：新建
        /// </summary>
        //[AccessSecurity(SecurityAction.Demand)]
        protected virtual void check_TaskRight_Update() { }
        /// <summary>
        /// 通过重写此方法，并标以AccessSecurity属性标签，指定其TaskCodes，实现过滤权限：修改
        /// </summary>
        //[AccessSecurity(SecurityAction.Demand)]
        protected virtual void check_TaskRight_Delete() { }
        #endregion

        protected IDbConnectionProvider SqlHelper { get { return this.connectionProvider; } }


        /// <summary> 统计
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public int Count(BaseFramework.IExpression expression = null)
        {
            return PersistentEntityMediator<T>.Count(connectionProvider, expression);
        }
        /// <summary> 对象是否存在
        /// </summary>
        /// <param name="primaryKey"></param>
        /// <returns></returns>
        public bool Exist(object primaryKey)
        {
            return PersistentEntityMediator<T>.Exist(connectionProvider, primaryKey);
        }
        /// <summary> 对象是否存在
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public bool Exist(BaseFramework.IExpression expression)
        {
            return PersistentEntityMediator<T>.Exist(connectionProvider, expression);
        }
        /// <summary> 获取一个对象
        /// </summary>
        /// <param name="primaryKey"></param>
        /// <returns></returns>
        public T Get(object primaryKey)
        {
            this.check_TaskRight_Get();
            return PersistentEntityMediator<T>.Get(connectionProvider, primaryKey);
        }
        /// <summary> 获取全部对象
        /// </summary>
        /// <returns></returns>
        public IEnumerable<T> GetAll()
        {
            this.check_TaskRight_Get();
            return PersistentEntityMediator<T>.GetAll(connectionProvider);
        }


        /// <summary> 获取第一个对象
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public T FindFirst(IExpression expression)
        {
            this.check_TaskRight_Get();
            return PersistentEntityMediator<T>.FindFirst(connectionProvider, expression, null);
        }
        /// <summary> 获取第一个对象
        /// </summary>
        /// <param name="orderParam"></param>
        /// <returns></returns>
        public T FindFirst(OrderParam orderParam)
        {
            this.check_TaskRight_Get();
            return this.FindFirst(null, orderParam);
        }
        /// <summary> 获取第一个对象
        /// </summary>
        /// <param name="searchParam"></param>
        /// <returns></returns>
        public T FindFirst(SearchParam searchParam)
        {
            this.check_TaskRight_Get();
            return this.FindFirst(searchParam, null);
        }
        /// <summary> 获取第一个对象
        /// </summary>
        /// <param name="searchParam"></param>
        /// <param name="orderParam"></param>
        /// <returns></returns>
        public T FindFirst(SearchParam searchParam, OrderParam orderParam)
        {
            this.check_TaskRight_Get();
            return PersistentEntityMediator<T>.FindFirst(connectionProvider, searchParam.Expression, orderParam);
        }

        /// <summary> 获取一个对象（存在多个时抛出异常）
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public T FindOne(IExpression expression)
        {
            this.check_TaskRight_Get();
            if (expression == null) throw new ArgumentNullException("expression");
            return PersistentEntityMediator<T>.FindOne(connectionProvider, expression);
        }
        /// <summary> 获取一个对象（存在多个时抛出异常）
        /// </summary>
        /// <param name="searchParam"></param>
        /// <returns></returns>
        public T FindOne(SearchParam searchParam)
        {
            this.check_TaskRight_Get();
            if (searchParam == null) throw new ArgumentNullException("searchParam");
            return this.FindOne(searchParam.Expression);
        }


        /// <summary> 获取对象集合
        /// </summary>
        /// <param name="searchParam"></param>
        /// <returns></returns>
        public T[] GetList(SearchParam searchParam)
        {
            this.check_TaskRight_Get();
            DataValid.IsNull(searchParam, "searchParam");
            var expression = searchParam != null ? searchParam.Expression : null;
            return PersistentEntityMediator<T>.GetList(connectionProvider, expression);
        }
        /// <summary> 获取对象集合
        /// </summary>
        /// <param name="searchParam"></param>
        /// <param name="orderParam"></param>
        /// <returns></returns>
        public T[] GetList(SearchParam searchParam, OrderParam orderParam)
        {
            this.check_TaskRight_Get();
            DataValid.IsNull(searchParam, "searchParam");
            var expression = searchParam != null ? searchParam.Expression : null;
            return PersistentEntityMediator<T>.GetList(connectionProvider, expression, orderParam);
        }
        /// <summary> 获取对象集合
        /// </summary>
        /// <param name="searchParam"></param>
        /// <param name="pageParam"></param>
        /// <returns></returns>
        public T[] GetList(SearchParam searchParam, ref PageParam pageParam)
        {
            this.check_TaskRight_Get();
            DataValid.IsNull(searchParam, "searchParam");
            var expression = searchParam != null ? searchParam.Expression : null;
            return PersistentEntityMediator<T>.GetList(connectionProvider, expression, ref pageParam);
        }
        /// <summary> 获取对象集合
        /// </summary>
        /// <param name="pageParam"></param>
        /// <returns></returns>
        public T[] GetList(ref PageParam pageParam)
        {
            this.check_TaskRight_Get();
            DataValid.IsNull(pageParam, "pageParam");
            return PersistentEntityMediator<T>.GetList(connectionProvider, null, ref pageParam);
        }
        /// <summary> 获取对象集合
        /// </summary>
        /// <param name="connectionProvider"></param>
        /// <param name="expression"></param>
        /// <param name="currentPage"></param>
        /// <param name="pageSize"></param>
        /// <param name="orderBy"></param>
        /// <param name="asc"></param>
        /// <returns></returns>
        public T[] GetList(IExpression expression, int currentPage = 1, int pageSize = int.MaxValue, string orderBy = null, bool asc = true)
        {
            this.check_TaskRight_Get();
            return PersistentEntityMediator<T>.GetList(connectionProvider, expression, currentPage, pageSize, orderBy, asc);
        }



        /// <summary> GetTable
        /// </summary>
        /// <param name="searchParam"></param>
        /// <returns></returns>
        public DataTable GetTable(SearchParam searchParam)
        {
            this.check_TaskRight_Get();
            DataValid.IsNull(searchParam, "searchParam");
            var expression = searchParam != null ? searchParam.Expression : null;
            return PersistentEntityMediator<T>.GetTable(connectionProvider, expression);
        }
        /// <summary> GetTable
        /// </summary>
        /// <param name="searchParam"></param>
        /// <param name="orderParam"></param>
        /// <returns></returns>
        public DataTable GetTable(SearchParam searchParam, OrderParam orderParam)
        {
            this.check_TaskRight_Get();
            DataValid.IsNull(searchParam, "searchParam");
            var expression = searchParam != null ? searchParam.Expression : null;
            return PersistentEntityMediator<T>.GetTable(connectionProvider, expression, orderParam);
        }
        /// <summary> GetTable
        /// </summary>
        /// <param name="searchParam"></param>
        /// <param name="pageParam"></param>
        /// <returns></returns>
        public DataTable GetTable(SearchParam searchParam, ref PageParam pageParam)
        {
            this.check_TaskRight_Get();
            DataValid.IsNull(searchParam, "searchParam");
            var expression = searchParam != null ? searchParam.Expression : null;
            return PersistentEntityMediator<T>.GetTable(connectionProvider, expression, ref pageParam);
        }
        /// <summary> GetTable
        /// </summary>
        /// <param name="pageParam"></param>
        /// <returns></returns>
        public DataTable GetTable(ref PageParam pageParam)
        {
            this.check_TaskRight_Get();
            DataValid.IsNull(pageParam, "pageParam");
            return PersistentEntityMediator<T>.GetTable(connectionProvider, null, ref pageParam);
        }
        /// <summary> GetTable
        /// </summary>
        /// <param name="connectionProvider"></param>
        /// <param name="expression"></param>
        /// <param name="currentPage"></param>
        /// <param name="pageSize"></param>
        /// <param name="orderBy"></param>
        /// <param name="asc"></param>
        /// <returns></returns>
        public DataTable GetTable(IExpression expression, int currentPage = 1, int pageSize = int.MaxValue, string orderBy = null, bool asc = true)
        {
            this.check_TaskRight_Get();
            return PersistentEntityMediator<T>.GetTable(connectionProvider, expression, currentPage, pageSize, orderBy, asc);
        }


        /// <summary> 保存对象
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool Save(T model)
        {
            if (model != null)
            {
                if (model.IsNew())
                    this.check_TaskRight_Create();
                else
                    this.check_TaskRight_Update();
            }
            string err = null;
            return PersistentEntityMediator<T>.Save(connectionProvider, model, out err);
        }
        /// <summary> 保存对象
        /// </summary>
        /// <param name="model"></param>
        /// <param name="err"></param>
        /// <returns></returns>
        public bool Save(T model, out string err)
        {
            if (model != null)
            {
                if (model.IsNew())
                    this.check_TaskRight_Create();
                else
                    this.check_TaskRight_Update();
            }
            return PersistentEntityMediator<T>.Save(connectionProvider, model, out err);
        }


        /// <summary> 新建对象。
        /// <para>新建失败时，将抛出异常</para>
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool Create(T model)
        {
            string err = null;
            return Create(model, out err);
        }
        /// <summary> 新建对象。
        /// </summary>
        /// <param name="model"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public bool Create(T model, out string err)
        {
            this.check_TaskRight_Create(); // 权限验证

            CancelEventExArgs cancel = new CancelEventExArgs(false, "不允许创建新信息");
            this.beforeCreate(model, cancel);
            if (cancel.Cancel) // 操作被取消
            {
                err = cancel.Error;
                return false;
            }

            var result = PersistentEntityMediator<T>.Create(connectionProvider, model, out err);
            if (result) this.afterCreate(model);

            return result;
        }


        /// <summary> 修改对象。
        /// <para>修改失败时，将抛出异常</para>
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool Update(T model)
        {
            string err = null;
            return Update(model, out err);
        }
        /// <summary> 修改对象。
        /// </summary>
        /// <param name="model"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public bool Update(T model, out string err)
        {
            this.check_TaskRight_Update(); // 权限验证

            CancelEventExArgs cancel = new CancelEventExArgs(false, "不允许修改信息");
            this.beforeUpdate(model, cancel);
            if (cancel.Cancel) // 操作被取消
            {
                err = cancel.Error;
                return false;
            }

            var result = PersistentEntityMediator<T>.Update(connectionProvider, model, out err);
            if (result) this.afterUpdate(model);

            return result;
        }


        /// <summary> 删除对象。
        /// <para>删除失败时，将抛出异常</para>
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool Delete(T model)
        {
            string err = null;
            return Delete(model, out err);
        }
        /// <summary> 删除对象。
        /// </summary>
        /// <param name="model"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public bool Delete(T model, out string err)
        {
            this.check_TaskRight_Delete(); // 权限验证

            //PersistentEntityMediator<T>.Refresh(connectionProvider, model); // 刷新对象状态

            CancelEventExArgs cancel = new CancelEventExArgs(false, "不允许删除信息");
            this.beforeDelete(model, cancel);
            if (cancel.Cancel) // 操作被取消
            {
                err = cancel.Error;
                return false;
            }

            var result = PersistentEntityMediator<T>.Delete(connectionProvider, model, out err);
            if (result) this.afterDelete(model);

            return result;
        }


        /// <summary> 删除对象集合
        /// <para>全部失败时，抛出异常</para>
        /// </summary>
        /// <param name="expression"></param>
        /// <returns>返回删除成功的行数。全部失败时，抛出异常</returns>
        public int DeleteByExpression(BaseFramework.IExpression expression = null)
        {
            string error = null;
            var result = DeleteByExpression(expression, out error);
            if (result == 0) throw new FrameworkException(error);

            return result;
        }
        /// <summary> 删除对象集合
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="error"></param>
        /// <returns>返回删除成功的行数。</returns>
        public int DeleteByExpression(BaseFramework.IExpression expression, out string error)
        {
            error = null;
            DataValid.IsNull(expression, "expression");
            this.check_TaskRight_Delete(); // 权限验证

            var models = this.GetList(expression);
            if (models == null || models.Length == 0)
            {
                error = "您要删除的数据不存在";
                return 0;
            }

            int succCount = 0;
            foreach (var model in models)
            {
                if (Delete(model)) succCount++;
            }

            return succCount;
        }


        /// <summary> 删除对象
        /// <para>失败时，抛出异常</para>
        /// </summary>
        /// <param name="primaryKey"></param>
        /// <returns>返回true删除成功；false删除失败。失败时，将抛出异常</returns>
        public bool DeleteByPrimaryKey(object primaryKey)
        {
            string error = null;
            var result = DeleteByPrimaryKey(primaryKey, out error);
            if (!result) throw new FrameworkException(error);

            return true;
        }
        /// <summary> 删除对象
        /// </summary>
        /// <param name="primaryKey"></param>
        /// <param name="error"></param>
        /// <returns>返回true删除成功；false删除失败。</returns>
        public bool DeleteByPrimaryKey(object primaryKey, out string error)
        {
            error = null;
            DataValid.IsNull(primaryKey, "primaryKey");
            this.check_TaskRight_Delete(); // 权限验证

            var model = Get(primaryKey);
            if (model == null)
            {
                error = "您要删除的数据不存在";
                return false;
            }

            return Delete(model, out error);
        }


        /// <summary> 删除对象集合
        /// <para>全部失败时，抛出异常</para>
        /// </summary>
        /// <param name="primaryKeys"></param>
        /// <returns>返回删除成功的行数。全部失败时，抛出异常</returns>
        public int DeleteByPrimaryKeys(object[] primaryKeys)
        {
            string error = null;
            var result = DeleteByPrimaryKeys(primaryKeys, out error);
            if (result == 0) throw new FrameworkException(error);

            return result;
        }
        /// <summary> 删除对象集合
        /// </summary>
        /// <param name="primaryKeys"></param>
        /// <param name="error"></param>
        /// <returns>返回删除成功的行数。</returns>
        public int DeleteByPrimaryKeys(object[] primaryKeys, out string error)
        {
            error = null;
            DataValid.IsNull(primaryKeys, "primaryKeys");
            this.check_TaskRight_Delete(); // 权限验证

            var models = PersistentEntityMediator<T>.GetListByPrimaryKeys(connectionProvider, primaryKeys);
            if (models == null || models.Length == 0)
            {
                error = "您要删除的数据不存在";
                return 0;
            }

            int succCount = 0;
            foreach (var model in models)
            {
                string err = null;
                if (Delete(model, out err))
                    succCount++;
                else
                {
                    if (error != null) error += System.Environment.NewLine;
                    error += err;
                }
            }

            return succCount;
        }


        #region virtual
        /// <summary>
        /// 新建前（可以调用此方法进行数据验证）
        /// </summary>
        /// <param name="model"></param>
        /// <param name="e"></param>
        public virtual void beforeCreate(T model, CancelEventExArgs e) { }
        /// <summary>
        /// 新建后
        /// </summary>
        /// <param name="model"></param>
        public virtual void afterCreate(T model) { }

        /// <summary>
        /// 修改前（可以调用此方法进行数据验证）
        /// </summary>
        /// <param name="model"></param>
        /// <param name="e"></param>
        public virtual void beforeUpdate(T model, CancelEventExArgs e) { }
        /// <summary>
        /// 修改后
        /// </summary>
        /// <param name="model"></param>
        public virtual void afterUpdate(T model) { }

        /// <summary>
        /// 删除前（可以调用此方法进行数据验证）
        /// </summary>
        /// <param name="model"></param>
        /// <param name="e"></param>
        public virtual void beforeDelete(T model, CancelEventExArgs e) { }
        /// <summary>
        /// 删除后
        /// </summary>
        /// <param name="model"></param>
        public virtual void afterDelete(T model) { }
        #endregion

        #region private
        
        #endregion
    }
}